Skip to content

Client Load Testing: simulate and send transactions #591

@sreuland

Description

@sreuland

Add support for the interactive transaction endpoints: simulateTransaction and sendTransaction. These endpoints require sophisticated request generation strategies based on transaction construction capabilities and leveraging the vegeta custom targeters to achieve parameter injections.

Related to: Client load testing tool Feature - #569
Related to: Client load testing Epic - #511

Prerequisite

Depends on #570, #572, and #573 to be done first. Create the CLI tool 'generate' and 'run' commands with data-dependent read-only endpoint support first.

Implementation Details

Use vegeta custom targets for injecting request data for the http client requests. Refer to this chat session for a vibe coded PoC of using vegeta against getTransaction.

Abstract away account creation so that we can plug in pubnet funding later.

Endpoint - simulateTransaction

Request Generation Strategy:

  • doesn't require seeded request data from bootstrap.dat from generate phase, request payload can be built during run
  • Mix of valid transactions:
    • 85% of requests should use well-formed valid transaction
    • 10% of requests should use transaction with invalid parameters
    • 5% of requests should use transaction with insufficient resources
  • Support both XDR and JSON format requests
  • At init time, pre-generate the XDR for three transactions: (1)well-formed, (2)invalid, and (3)insufficient resource
    • Transaction envelopes built with single InvokeHostFn op to invoke contract 'transfer' function
    • Can use zero contract ID since simulation doesn't validate on-chain existence
    • Can use zero account ID for account to/from references

Endpoint - sendTransaction

Request Generation Strategy:

  • Transaction submission pattern:

    • transactions will be done for 'transfer' operations on classic and soroban.
    • At worker thread init time:
      • generate a keypair for pub/private keys for the signer which is also used as the source and the transfer from accoun.
      • generate keypairss for transfer 'to' accounts, one or many, your choice.
      • fund the signer account public key with Friendbot
    • worker constructs and sign all transactions with signer account keypair, and set the 'source' on tx to the signer public key and correctly incrementing the account sequence number,
    • Handle transaction lifecycle (async submission, poll on getTransaction, result tracking)
  • if sendTransaction endpoint load testing is enabled in loadtest_config.toml, it should Include warnings about network impact on console from run.

    • if enabled, should the cli tool validate if pubnet is specified as network passphrase and fail the test on console with reason?
  • doesn't require seeded request data from bootstrap.dat from generate phase, request payload can be built during run

  • Perform the 'transfer' type transactions for both classic and contracts based on the classic_ratio configuration:

    Classic Stellar Payments (XLM transfers):

    • Percentage of transactions submitted determined by sendTransaction.classic_ratio (0-100)
    • Use generated 'from' and 'to' accounts
    • Transfer XLM as the asset

    Soroban SEP-41 Token Transfers:

    • Percentage of transactions submitted determined by 100 - sendTransaction.classic_ratio
    • Invoke 'transfer' method on SEP-41 compliant token contract
    • Use generated 'from' and 'to' accounts
    • at worker init, mint tokens to 'from' accounts
    • Token contract specified by sendTransaction.soroban_sep41_token_contract (WASM file path or hex contract ID). If it's wasm, then test should deploy the contract to network at init time.
    • Leverage the SEP-41 compliant token interface so invocation is just for the standardized 'transfer' function and the contract instance can be an SAC or a custom token contract.

Configuration Updates

Update TOML configuration to include new endpoints with transaction-specific parameters:

[endpoints]
# Existing endpoints...
# getHealth.rps = 5.0
# ...

# Transaction simulation endpoint
simulateTransaction.enabled = true
simulateTransaction.rps = 3.0
simulateTransaction.concurrency = 2

# Transaction sending endpoint
sendTransaction.enabled = true
sendTransaction.rps = 1.0
sendTransaction.concurrency = 1

# Transaction type distribution (0-100, remainder is Soroban)
sendTransaction.classic_ratio = 50

# SEP-41 token contract
# Can be any SAC or SEP-41 compliant token contract
# expressed as file path to a wasm, which would be deployed by test first to network
sendTransaction.soroban_sep41_token_contract = "./contracts/token.wasm"
# or as strkey encoded contract address for a contract already on chain
sendTransaction.soroban_sep41_token_contract = "CDABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF"

Metrics

Update metrics collection to include transaction-specific measurements:

New Metrics:

  • rpc_loadtest_simulate_result{type="success|fail"} - Simulation response counter
  • rpc_loadtest_send_transaction_type{type="classic|soroban"} - Transaction type counter
  • rpc_loadtest_send_transaction_result{type="success|fail"} - Submission response counter

Update console output to include:

[00:32 / 05:00] 
simulateTransaction: 180 req (153 success, 27 errors) | 3.0 RPS | p50: 85ms, p95: 220ms, p99: 450ms
  └─ Avg CPU: 1.2M, Avg Memory: 45KB, Success Rate: 85%
sendTransaction: 60 req (58 success, 2 errors) | 1.0 RPS | p50: 120ms, p95: 380ms, p99: 650ms
  └─ Classic: 30 (50%), Soroban: 30 (50%) | Validation Rate: 97%

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Status

    To Do

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions